# encoding: utf-8
"""
语音识别传感器模块
公司: 深圳市幻尔科技有限公司
官网: hiwonder.com
作者: Aiden
日期: 2019/9/20

使用说明:
1. 只能识别汉字，需要将汉字转换成拼音字母，每个汉字之间用空格隔开
   例如：幻尔科技 --> huan er ke ji
2. 最多添加50个词条，每个词条最长为79个字符，每个词条最多10个汉字
3. 每个词条对应一个识别号(1~255)，不同词条可以使用相同识别号
4. 模块状态灯说明：
   - 亮起：正在识别语音
   - 熄灭：未在识别语音
   - 变暗/闪烁：识别到语音
   - 恢复：读取结果后恢复当前状态
"""

from robot_core import action_executor
import smbus
import time
from typing import Optional, List, Union
from robot_core.action_executor import ActionExecutor
from robot_core.servo_controller import servo_controller


# 常量定义
class ASRConstants:
    # I2C 地址
    DEFAULT_ADDRESS = 0x79

    # 寄存器地址
    ASR_RESULT_ADDR = 100  # 识别结果存放地址
    ASR_WORDS_ERASE_ADDR = 101  # 擦除所有词条
    ASR_MODE_ADDR = 102  # 识别模式设置

    # 识别模式
    MODE_LOOP = 1  # 循环识别模式，状态灯常亮
    MODE_PASSWORD = 2  # 口令模式，以第一个词条为口令
    MODE_BUTTON = 3  # 按键模式，按下开始识别

    # 词条添加起始地址
    ASR_ADD_WORDS_ADDR = 160


class ASRSensor:
    """语音识别传感器类"""

    def __init__(self, address: int = ASRConstants.DEFAULT_ADDRESS, bus: int = 1):
        """
        初始化ASR传感器

        Args:
            address: I2C设备地址
            bus: I2C总线号
        """
        self.address = address
        self.bus = smbus.SMBus(bus)

    def read_byte(self) -> int:
        """读取一个字节数据"""
        return self.bus.read_byte(self.address)

    def write_byte(self, val: int) -> bool:
        """写入一个字节数据"""
        try:
            self.bus.write_byte(self.address, val)
            return True
        except Exception:
            return False

    def write_data(self, reg: int, val: int) -> None:
        """写入寄存器数据"""
        self.bus.write_byte(self.address, reg)
        self.bus.write_byte(self.address, val)

    def get_result(self) -> int:
        """
        获取识别结果

        Returns:
            int: 识别结果编号，-1表示读取失败
        """
        if not self.write_byte(ASRConstants.ASR_RESULT_ADDR):
            return -1
        return self.bus.read_byte(self.address)

    def add_words(self, id_num: int, words: str) -> bool:
        """
        添加识别词条

        Args:
            id_num: 识别号(1-255)
            words: 要识别的汉字拼音，用空格分隔

        Returns:
            bool: 是否添加成功
        """
        try:
            buf = [id_num]
            for char in words:
                buf.append(ord(char))
            self.bus.write_i2c_block_data(
                self.address, ASRConstants.ASR_ADD_WORDS_ADDR, buf
            )
            time.sleep(0.05)
            return True
        except Exception:
            return False

    def erase_words(self) -> bool:
        """擦除所有词条"""
        try:
            result = self.bus.write_byte_data(
                self.address, ASRConstants.ASR_WORDS_ERASE_ADDR, 0
            )
            time.sleep(0.06)
            return result == 0
        except Exception:
            return False

    def set_mode(self, mode: int) -> bool:
        """
        设置识别模式

        Args:
            mode: 1-循环识别模式, 2-口令模式, 3-按键模式

        Returns:
            bool: 是否设置成功
        """
        try:
            result = self.bus.write_byte_data(
                self.address, ASRConstants.ASR_MODE_ADDR, mode
            )
            return result == 0
        except Exception:
            return False


def main():
    """主函数示例"""
    # 初始化ASR传感器
    asr = ASRSensor()

    action_executor = ActionExecutor()

    # 配置词条和识别模式（可以掉电保存）
    if True:  # 设置为False可以跳过初始化
        asr.erase_words()
        asr.set_mode(ASRConstants.MODE_LOOP)

        # 添加识别词条
        commands = {
            1: "ni hao",  # 你好
            2: "ting zhi",  # 停止
            3: "li zheng",  # 站立
            4: "xiang qian",  # 向前
            5: "xiang hou",  # 向后
            6: "xiang zuo",  # 向左
            7: "xiang you",  # 向右
            8: "kuai su you zhuan",  # 快速右转
            10: "zhan dou mo shi",  # 站立不动
            11: "gong ji duo duo",  # 恭喜恭喜
        }

        for id_num, words in commands.items():
            asr.add_words(id_num, words)

    # 主循环
    while True:
        data = asr.get_result()
        print(f"识别结果: {data}")

        if data == 2:
            action_executor.run_action("25")
        elif data == 3:
            servo_controller.set_position(0, 0)
        elif data == 4:
            action_executor.run_action_group("26", 5)
            time.sleep(1)
        elif data == 5:
            action_executor.run_action_group("27", 5)
            time.sleep(1)
        elif data == 6:
            action_executor.run_action_group("28", 1)
        elif data == 7:
            action_executor.run_action_group("29", 1)
        elif data == 8:
            action_executor.run_action("40")
        elif data in (10, 11):
            action_executor.run_action("10")


if __name__ == "__main__":
    main()
